package com.tduck.cloud.form.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tduck.cloud.common.entity.BaseEntity;
import com.tduck.cloud.common.entity.SysBaseEntity;
import com.tduck.cloud.common.exception.BusinessException;
import com.tduck.cloud.common.util.AsyncProcessUtils;
import com.tduck.cloud.common.util.JsonUtils;
import com.tduck.cloud.common.util.RedisUtils;
import com.tduck.cloud.common.util.Result;
import com.tduck.cloud.form.constant.FormRedisConstants;
import com.tduck.cloud.form.entity.FormDataSourceEntity;
import com.tduck.cloud.form.service.FormDataSourceService;
import com.tduck.cloud.form.vo.UserFormDataVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
public class FormSyncUtils {

    @Resource
    private FormDataSourceService formDataSourceService;
    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private RedisUtils redisUtils;

    /**
     * 同步字段
     */
    public void syncField(String url, Long id) {
        if (StrUtil.isBlank(url)) {
            return;
        }
        String result = HttpUtil.get(url.trim());
        Result resultObj = JsonUtils.jsonToObj(result, Result.class);
        if (!resultObj.isSuccess()) {
            throw new BusinessException(resultObj.getMsg());
        }
        FormDataSourceEntity formDataSource = new FormDataSourceEntity();
        formDataSource.setId(id);
        JSON json = JSONUtil.parse(resultObj.getData());
        formDataSource.setFormKey(json.getByPath("formKey", String.class));
        formDataSource.setFields(json.getByPath("fields", JSONArray.class));
        formDataSourceService.updateById(formDataSource);
        if (!mongoTemplate.collectionExists(formDataSource.getFormKey())) {
            mongoTemplate.createCollection(formDataSource.getFormKey());
        }
    }

    /**
     * 同步数据
     */
    public void syncData(String url, Long id) {
        if (StrUtil.isBlank(url)) {
            return;
        }
        FormDataSourceEntity dataSourceEntity = formDataSourceService.getById(id);
        String formKey = dataSourceEntity.getFormKey();
        Long current = 1L;
        Long size = 200L;
        while (true) {
            if (current == 1) {
                mongoTemplate.dropCollection(formKey);
                mongoTemplate.createCollection(formKey);
            }
            String result = HttpUtil.get(url.trim() + "&current" + current + "&size=" + size);
            Result resultObj = JsonUtils.jsonToObj(result, Result.class);
            if (!resultObj.isSuccess()) {
                throw new BusinessException(resultObj.getMsg());
            }
            Page page = JSONUtil.toBean(JSONUtil.toJsonStr(resultObj.getData()), Page.class);
            long total = page.getTotal();
            if (total == 0) {
                break;
            }
            List<UserFormDataVO> list = JsonUtils.jsonToList(JsonUtils.objToJson(page.getRecords()), UserFormDataVO.class);
            if (CollUtil.isNotEmpty(list)) {
                for (UserFormDataVO map : list) {
                    mongoTemplate.insert(convertDocument(map), formKey);
                }
            }
            current += 1;
            // 是否是最后一一页
            if (current * size >= total) {
                redisUtils.set(StrUtil.format(FormRedisConstants.FORM_DATA_COUNT, formKey), total);
                break;
            }
        }

    }


    /**
     * 更新
     *
     * @param result  数据
     * @param formKey 表单key
     */
    public void insert(Map<String, Object> result, String formKey) {
        mongoTemplate.insert(result, formKey);
    }

    /**
     * 更新
     *
     * @param result  数据
     * @param formKey 表单key
     */
    public void updateFirstById(Map<String, Object> result, String formKey) {
        // 是否存在 存在的话更新 不存在的话新增
        Query query = Query.query(Criteria.where("id").is(result.get("id")));
        Update update = new Update();
        result.forEach(update::set);
        mongoTemplate.updateFirst(query, update, formKey);
    }


    public void delete(Long id, String formKey) {
        mongoTemplate.remove(Query.query(Criteria.where("id").is(id)), formKey);
    }


    /**
     * 转换
     *
     * @param result 数据
     * @return Map
     */
    private Map<String, Object> convertDocument(UserFormDataVO result) {
        Map<String, Object> processData = result.getOriginalData();
        Map<String, Object> resultMap = BeanUtil.beanToMap(result);
        //格式化时间
        resultMap.put(BaseEntity.Fields.updateTime, LocalDateTimeUtil.formatNormal(result.getUpdateTime()));
        resultMap.put(BaseEntity.Fields.createTime, LocalDateTimeUtil.formatNormal(result.getCreateTime()));
        resultMap.remove(UserFormDataVO.Fields.originalData);
        processData.putAll(resultMap);
        resultMap.keySet().forEach(key -> {
            if (StrUtil.startWithAny(key, "date", "input")) {
                processData.put(key, MapUtil.getStr(resultMap, key));
            }
        });
        processData.remove(SysBaseEntity.Fields.searchValue);
        processData.remove(SysBaseEntity.Fields.params);
        return processData;
    }

}
